﻿/*
-----------------------------------------------------------------------------
This source file is part of Cell Cloud.

Copyright (c) 2009-2012 Cell Cloud Team - cellcloudproject@gmail.com

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-----------------------------------------------------------------------------
*/

#ifndef CellMemorySTLAllocator_h
#define CellMemorySTLAllocator_h

#include "CellPrerequisites.h"
#include "CellHeaderPrefix.h"

namespace cell
{

// 基本 STL 分配类。
template<typename T>
struct STLAllocatorBase
{
	typedef T value_type;	// 基类的通用分配器
};

// 基本 STL 分配类（const T 模板版本）。
template<typename T>
struct STLAllocatorBase<const T>
{
	typedef T value_type;	// 基类的通用分配器
};

template
	<
	typename T,
	typename AllocPolicy
	>
class STLAllocator : public STLAllocatorBase<T>
{
public :
	/// 定义自己的数据类型，依据 ISO C++ 。
	typedef STLAllocatorBase<T>			Base;
	typedef typename Base::value_type	value_type;
	typedef value_type*					pointer;
	typedef const value_type*			const_pointer;
	typedef value_type&					reference;
	typedef const value_type&			const_reference;
	typedef std::size_t					size_type;
	typedef std::ptrdiff_t				difference_type;


	/// 标准重绑定机制。
	template<typename U>
	struct rebind
	{
		typedef STLAllocator<U, AllocPolicy> other;
	};

	/// 构造
	inline explicit STLAllocator()
	{ }

	/// 析构
	virtual ~STLAllocator()
	{ }

	/// 拷贝构造
	inline STLAllocator( STLAllocator const& )
	{ }

	/// 转型
	template <typename U>
	inline STLAllocator( STLAllocator<U, AllocPolicy> const& )
	{ }

	/// 转型
	template <typename U, typename P>
	inline STLAllocator( STLAllocator<U, P> const& )
	{ }

	/// 内存分配器，使用 STL。
	inline pointer allocate( size_type count,
		typename std::allocator<void>::const_pointer ptr = 0 )
	{
		(void)ptr;
		// convert request to bytes
		register size_type sz = count*sizeof( T );
		pointer p  = static_cast<pointer>(AllocPolicy::allocateBytes(sz));
		return p;
	}

	/// 内存释放器，使用 STL。
	inline void deallocate( pointer ptr, size_type )
	{
		// convert request to bytes, but we can't use this?
		// register size_type sz = count*sizeof( T );
		AllocPolicy::deallocateBytes(ptr);
	}

	pointer address(reference x) const
	{
		return &x;
	}

	const_pointer address(const_reference x) const
	{
		return &x;
	}

	size_type max_size() const throw()
	{
		// maximum size this can handle, delegate
		return AllocPolicy::getMaxAllocationSize();
	}

	void construct(pointer p, const T& val)
	{
		// call placement new
		new(static_cast<void*>(p)) T(val);
	}

	void destroy(pointer p)
	{
		// do we have to protect against non-classes here?
		// some articles suggest yes, some no
		p->~T();
	}

};

/// 比较是否相等。由其他分配器分配的内存是否可由该分配器释放（ISO C++）。
template<typename T, typename T2, typename P>
inline bool operator==(STLAllocator<T,P> const&,
	STLAllocator<T2,P> const&)
{
	// 一般的，其他分配器分配的内存都可以被释放。
	return true;
}

/// 比较是否相等。由其他分配器分配的内存是否可由该分配器释放（ISO C++）。
template<typename T, typename P, typename OtherAllocator>
inline bool operator==(STLAllocator<T,P> const&,
	OtherAllocator const&)
{
	return false;
}
/// 比较是否相等。由其他分配器分配的内存是否可由该分配器释放（ISO C++）。
template<typename T, typename T2, typename P>
inline bool operator!=(STLAllocator<T,P> const&,
	STLAllocator<T2,P> const&)
{
	return false;
}

/// 比较是否相等。由其他分配器分配的内存是否可由该分配器释放（ISO C++）。
template<typename T, typename P, typename OtherAllocator>
inline bool operator!=(STLAllocator<T,P> const&,
	OtherAllocator const&)
{
	return true;
}

} // end namespace cell

#include "CellHeaderSuffix.h"

#endif // CellMemorySTLAllocator_h
